

package cn.shengchao.examstar.distribute.ohs.local.appservice.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.shengchao.base.enums.DisEnableStatusEnum;
import cn.shengchao.examstar.rpc.distribute.enums.*;
import cn.shengchao.examstar.distribute.exception.DistributeException;
import cn.shengchao.examstar.distribute.infrastrure.po.DistributeNodeInfo;
import cn.shengchao.examstar.distribute.infrastrure.po.DistributeNodeRole;
import cn.shengchao.examstar.distribute.infrastrure.po.DistributeNodeRoleChain;
import cn.shengchao.examstar.distribute.infrastrure.service.DistributeNodeInfoService;
import cn.shengchao.examstar.distribute.infrastrure.service.DistributeNodeRoleChainService;
import cn.shengchao.examstar.distribute.infrastrure.service.DistributeNodeRoleService;
import cn.shengchao.examstar.distribute.model.DistributeNodeRoleChainCreator;
import cn.shengchao.examstar.distribute.model.DistributeNodeRoleChainExistModel;
import cn.shengchao.examstar.distribute.ohs.local.appservice.DistributeNodeRoleChainDomainService;
import cn.shengchao.examstar.distribute.ohs.local.appservice.DistributeNodeRoleChainExistLoader;
import cn.shengchao.examstar.rpc.base.exception.BaseRpcException;
import cn.shengchao.examstar.rpc.distribute.dto.*;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.continew.starter.core.exception.BaseException;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: examstarapi
 * @description: 用户分销链综合业务处理实现
 * @author: Xiong weiqiang
 * @create: 2025-03-25 20:08
 */
@Service
@RequiredArgsConstructor
public class DistributeNodeRoleChainDomainServiceImpl implements DistributeNodeRoleChainDomainService {
    private final DistributeNodeRoleService distributeNodeRoleService;
    private final DistributeNodeInfoService distributeNodeInfoService;
    private final DistributeNodeRoleChainService distributeNodeRoleChainService;
    private final DistributeNodeRoleChainExistLoader distributeNodeRoleChainExistLoader;
    @Transactional
    @Override
    public void createDistributeNodeAndRoleChainAfterClean(DistributeNodeBaseCreateDto distributeNodeInfoCreateDto) {
        DistributeNodeInfo upLevelNode = null;
        if (distributeNodeInfoCreateDto.getUpLevelUserId() != null) {
            if (distributeNodeInfoCreateDto.getUpLevelUserId() == 0L) {
                upLevelNode = DistributeNodeRoleChainCreator.buildPlatformNodeInfo();
            } else {
                //查询上级节点
                upLevelNode = distributeNodeInfoService.getOne(Wrappers.lambdaQuery(DistributeNodeInfo.class)
                    .eq(DistributeNodeInfo::getUserId, distributeNodeInfoCreateDto.getUpLevelUserId())
                        .eq(DistributeNodeInfo::getDistributeType, distributeNodeInfoCreateDto.getDistributeType())
                    .eq(DistributeNodeInfo::getDataStatus, DistributeDataValidEnum.STATUS_VALID.getStatus()));

            }
        }
        if (upLevelNode == null) {
            throw new BaseRpcException("建立分销用户错误：：上级节点构建错误，" + distributeNodeInfoCreateDto.getUpLevelUserId());
        }
        //处理完用户以前分销链数据后，开始创建新的分销链数据
        DistributeNodeRoleChainCreator nodeRoleChainCreator = DistributeNodeRoleChainCreator
            .buildCreatorFromCreateDto(distributeNodeInfoCreateDto, upLevelNode);
        try {
            cleanUserNodeRoleChain(distributeNodeInfoCreateDto.getUserId(),distributeNodeInfoCreateDto.getDistributeType());
            createUserNewNodeRoleChainAfterCheckAndClean(nodeRoleChainCreator);
        } catch (Exception e) {
            throw new BaseException("建立分销用户错误：" + e.getMessage());
        }
    }

    /**
     * method : editDistributeUserStablePercent
     * description : 更改分销节点用户的分成比例，节点不变，新建一份角色设置新比例，原角色数据改历史
     *
     * @param distributeUserInfoPercentDto \{@link DistributeNodeInfoPercentDto \}
     * @author : Xiong weiqiang
     * @CreateDate : 2025-03-26 10:53:35
     * @Reviewed :
     * @UpdateLog : Name Date Reason/Contents
     *            ---------------------------------------
     *            **** **** ****
     */
    @Transactional
    @Override
    public void editDistributeUserStablePercent(DistributeNodeInfoPercentDto distributeUserInfoPercentDto) {
        DistributeNodeRoleChainExistModel existModel = null;
        try {
            existModel = distributeNodeRoleChainExistLoader.loadModelByUserId(distributeUserInfoPercentDto
                .getUserId(), DistributeTypeEnum.TYPE_SALE.getType());
        } catch (DistributeException e) {
            throw new BaseRpcException("更改分销节点比例时错误：加载原分销体系数据错误：" + e.getMessage());
        }

        DistributeNodeRole distributeNodeRole = existModel.getDistributeNodeRole();
        DistributeNodeRole updateNodeRole = new DistributeNodeRole();
        BeanUtil.copyProperties(distributeNodeRole, updateNodeRole);
        updateNodeRole.setPercentStable(distributeUserInfoPercentDto.getPercentStable());
        updateNodeRole.setId(null);
        //TODO:改比例，考虑锁
        distributeNodeRoleService.save(updateNodeRole);
        //把前面的改为历史状态
        distributeNodeRole.setEndTime(new Date());
        distributeNodeRole.setDataStatus(DistributeDataStatusEnum.STATUS_HIS.getStatus());
        distributeNodeRoleService.updateById(distributeNodeRole);
        distributeNodeInfoService
                .update(Wrappers.lambdaUpdate(DistributeNodeInfo.class).eq(DistributeNodeInfo::getId,
                        existModel.getDistributeNodeInfo().getId())
                        .set(DistributeNodeInfo::getDistributeUserRoleId,updateNodeRole.getId()));
    }

    /**
     * method : changeDistributeUserUpLevelNode
     * description : 变化父节点
     *
     * @param distributeUserInfoChangeNodeDto \{@link DistributeNodeInfoChangeNodeDto \}
     * @author : Xiong weiqiang
     * @CreateDate : 2025-03-26 11:32:37
     * @Reviewed :
     * @UpdateLog : Name Date Reason/Contents
     *            ---------------------------------------
     *            **** **** ****
     */
    @Transactional
    @Override
    public void changeDistributeUserUpLevelNode(DistributeNodeInfoChangeNodeDto distributeUserInfoChangeNodeDto) {
        DistributeNodeRoleChainExistModel existModel = null;
        try {
            existModel = distributeNodeRoleChainExistLoader.loadModelByUserId(distributeUserInfoChangeNodeDto
                .getUserId(), distributeUserInfoChangeNodeDto.getDistributeType().getType());
        } catch (DistributeException e) {
            throw new BaseRpcException("修改分销用户上级节点时错误：加载原分销体系数据错误：" + e.getMessage());
        }
        //变更的父节点
        DistributeNodeInfo upLevelNode = null;
        if (distributeUserInfoChangeNodeDto.getUpLevelUserId() == 0L ) {
            //改挂平台,重建节点，重建角色，重建链
            upLevelNode = DistributeNodeRoleChainCreator.buildPlatformNodeInfo();

        } else {
            List<DistributeNodeInfo> upLevelNodes = distributeNodeInfoService.list(Wrappers
                .lambdaQuery(DistributeNodeInfo.class)
                .eq(DistributeNodeInfo::getDistributeType, distributeUserInfoChangeNodeDto.getDistributeType().getType())
                .eq(DistributeNodeInfo::getUserId, distributeUserInfoChangeNodeDto.getUpLevelUserId())
                .eq(DistributeNodeInfo::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
            if (CollUtil.isEmpty(upLevelNodes) || upLevelNodes.size() != 1) {
                throw new BaseRpcException("修改分销用户上级节点时错误：父级节点数量" + (CollUtil.isNotEmpty(upLevelNodes)
                    ? upLevelNodes.size()
                    : 0));
            }
            upLevelNode = upLevelNodes.getFirst();
        }
        //建立新模型
        DistributeNodeRoleChainCreator distributeNodeRoleChainCreator = existModel.buildCreatorFromExistModel();
        if (distributeUserInfoChangeNodeDto.getPercentStable() != null) {
            distributeNodeRoleChainCreator.setPercentStable(distributeUserInfoChangeNodeDto.getPercentStable());
        }
        //加盟商员工角色的管理员设置要改掉。
        if (DistributeSaleRoleEnum.ROLE_DSPD_EMP.getCode().equals(distributeNodeRoleChainCreator.getDistributeRoleCode())){
            distributeNodeRoleChainCreator.setAdminUserId(distributeUserInfoChangeNodeDto.getUpLevelUserId());
        }
        if (DistributeContentRoleEnum.ROLE_CTPD_EMP.getCode().equals(distributeNodeRoleChainCreator.getDistributeRoleCode())){
            distributeNodeRoleChainCreator.setAdminUserId(distributeUserInfoChangeNodeDto.getUpLevelUserId());
        }
        distributeNodeRoleChainCreator.setId(null);
        distributeNodeRoleChainCreator.setUpLevelDistributeNodeInfo(upLevelNode);
        try {
            //清除原分销链
            cleanUserNodeRoleChain(distributeUserInfoChangeNodeDto.getUserId(),distributeUserInfoChangeNodeDto.getDistributeType().getType());
            //重建分销链
            createUserNewNodeRoleChainAfterCheckAndClean(distributeNodeRoleChainCreator);
        } catch (Exception e) {
            throw new BaseException("修改分销用户上级节点时错误：" + e.getMessage());
        }
        //加盟商角色的换绑还得把底下分销节点的链儿全部改掉。。。
        if (DistributeSaleRoleEnum.ROLE_DSPD.getCode().equals(distributeNodeRoleChainCreator.getDistributeRoleCode())){
            DistributeNodeInfo dspdNewNode=distributeNodeInfoService.getNodeInfoForUser(distributeUserInfoChangeNodeDto.getUserId(),DistributeTypeEnum.TYPE_SALE);
            distributeNodeRoleChainService.updateDspdLowNodeToNewNode(existModel.getDistributeNodeInfo().getId(),dspdNewNode.getId());
        }

    }

    /**
     * method : changeDistributeUserEmployeeLeave
     * description : 处理员工离职
     *
     * @param distributeNodeInfoEmployeeLeaveDto \{@link DistributeNodeInfoEmployeeLeaveDto \}
     * @author : Xiong weiqiang
     * @CreateDate : 2025-03-26 11:29:29
     * @Reviewed :
     * @UpdateLog : Name Date Reason/Contents
     *            ---------------------------------------
     *            **** **** ****
     */
    @Transactional
    @Override
    public void changeDistributeUserEmployeeLeave(DistributeNodeInfoEmployeeLeaveDto distributeNodeInfoEmployeeLeaveDto) {
        List<DistributeNodeInfo> nodeInfoList = distributeNodeInfoService.list(Wrappers
            .lambdaQuery(DistributeNodeInfo.class)
                .eq(DistributeNodeInfo::getDistributeType, distributeNodeInfoEmployeeLeaveDto.getDistributeType())
            .eq(DistributeNodeInfo::getUserId, distributeNodeInfoEmployeeLeaveDto.getUserId())
            .eq(DistributeNodeInfo::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
        List<DistributeNodeRole> nodeRoleList = distributeNodeRoleService.list(Wrappers
            .lambdaQuery(DistributeNodeRole.class)
            .eq(DistributeNodeRole::getUserId, distributeNodeInfoEmployeeLeaveDto.getUserId())
                .eq(DistributeNodeRole::getDistributeType, distributeNodeInfoEmployeeLeaveDto.getDistributeType())
            .eq(DistributeNodeRole::getRoleCode, distributeNodeInfoEmployeeLeaveDto.getDistributeRoleCode())
            .eq(DistributeNodeRole::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
        List<DistributeNodeRoleChain> nodeRoleChainList = distributeNodeRoleChainService.list(Wrappers
            .lambdaQuery(DistributeNodeRoleChain.class)
            .eq(DistributeNodeRoleChain::getRefUserId, distributeNodeInfoEmployeeLeaveDto.getUserId())
                .eq(DistributeNodeRoleChain::getDistributeType, distributeNodeInfoEmployeeLeaveDto.getDistributeType())
            .eq(DistributeNodeRoleChain::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
        if (CollUtil.isNotEmpty(nodeInfoList) && nodeInfoList.size() == 1) {
            if (CollUtil.isNotEmpty(nodeRoleList) && nodeRoleList.size() == 1) {
                if (CollUtil.isNotEmpty(nodeRoleChainList) && nodeRoleChainList.size() == 1) {
                    //把员工的改为历史状态
                    cleanUserNodeRoleChain(distributeNodeInfoEmployeeLeaveDto.getUserId(), distributeNodeInfoEmployeeLeaveDto.getDistributeType());
                } else {
                    throw new BaseRpcException("清理员工记录错误：节点用户链记录数量" + (CollUtil.isNotEmpty(nodeRoleChainList)
                        ? nodeRoleChainList.size()
                        : 0));
                }
            } else {
                throw new BaseRpcException("清理员工记录错误：节点用户角色数量" + (CollUtil.isNotEmpty(nodeRoleList)
                    ? nodeRoleList.size()
                    : 0));
            }
        } else {
            throw new BaseRpcException("清理员工记录错误：节点数量" + (CollUtil.isNotEmpty(nodeInfoList)
                ? nodeInfoList.size()
                : 0));
        }
    }

    /**
     * method : createUserNewNodeRoleChainAfterCheckAndClean
     * description : 创建分销链体系（不考虑节点，在调用之前，处理好分销用户以前的数据，保证用户无相关生效数据）
     *
     * @param nodeRoleChainCreator \{@link DistributeNodeRoleChainCreator \}
     * @author : Xiong weiqiang
     * @CreateDate : 2025-03-26 13:06:44
     * @Reviewed :
     * @UpdateLog : Name Date Reason/Contents
     *            ---------------------------------------
     *            **** **** ****
     */
    private void createUserNewNodeRoleChainAfterCheckAndClean(DistributeNodeRoleChainCreator nodeRoleChainCreator) throws DistributeException {
        if (nodeRoleChainCreator == null || nodeRoleChainCreator.getUpLevelDistributeNodeInfo() == null) {
            throw new BaseRpcException("重建分销节点链时模型错误：模型检查错误");
        }
        long nodeCount = distributeNodeInfoService.count(Wrappers.lambdaQuery(DistributeNodeInfo.class)
            .eq(DistributeNodeInfo::getUserId, nodeRoleChainCreator.getUserId())
                .eq(DistributeNodeInfo::getDistributeType, nodeRoleChainCreator.getDistributeType())
            .eq(DistributeNodeInfo::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
        long roleCount = distributeNodeRoleService.count(Wrappers.lambdaQuery(DistributeNodeRole.class)
            .eq(DistributeNodeRole::getUserId, nodeRoleChainCreator.getUserId())
                .eq(DistributeNodeRole::getDistributeType, nodeRoleChainCreator.getDistributeType())
            .eq(DistributeNodeRole::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
        long chainCount = distributeNodeRoleChainService.count(Wrappers.lambdaQuery(DistributeNodeRoleChain.class)
            .eq(DistributeNodeRoleChain::getRefUserId, nodeRoleChainCreator.getUserId())
                .eq(DistributeNodeRoleChain::getDistributeType, nodeRoleChainCreator.getDistributeType())
            .eq(DistributeNodeRoleChain::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
        if (nodeCount == 0 && roleCount == 0 && chainCount == 0) {
            DistributeNodeRole nodeRole = nodeRoleChainCreator.buildRoleInfo();
            nodeRole.setUpLevel(nodeRoleChainCreator.getUpLevelDistributeNodeInfo().getDistributeRoleLevel());
            distributeNodeRoleService.save(nodeRole);
            nodeRoleChainCreator.setDistributeUserRoleId(nodeRole.getId());
            DistributeNodeInfo nodeInfo = new DistributeNodeInfo();
            BeanUtil.copyProperties(nodeRoleChainCreator, nodeInfo);
            nodeInfo.setEnableStatus(DisEnableStatusEnum.ENABLE.getValue());
            nodeInfo.setDataStatus(DistributeDataStatusEnum.STATUS_CURT.getStatus());
            nodeInfo.setDistributeRoleLevel(nodeRoleChainCreator.getDistributeRoleLevel());
            distributeNodeInfoService.save(nodeInfo);
            nodeRoleChainCreator.setId(nodeInfo.getId());
            distributeNodeRoleChainService.save(nodeRoleChainCreator.buildNodeRoleChain());
        } else {
            if (nodeCount != 0) {
                throw new DistributeException("建立用户分销体系错误：节点数量" + nodeCount);
            }
            if (roleCount != 0) {
                throw new DistributeException("建立用户分销体系错误：角色数量" + roleCount);
            }
            throw new DistributeException("建立用户分销体系错误：链数量" + nodeCount);
        }
    }

    /**
     * method : cleanUserNodeRoleChain
     * description : 单纯清理分销链体系,完全不考虑业务的逻辑
     *
     * @param userId \{@link Long \}
     * @param distributeType \{@link Integer \}
     * @author : Xiong weiqiang
     * @CreateDate : 2025-03-26 13:17:30
     * @Reviewed :
     * @UpdateLog : Name Date Reason/Contents
     *            ---------------------------------------
     *            **** **** ****
     */
    private void cleanUserNodeRoleChain(Long userId,Integer distributeType) throws DistributeException {
        distributeNodeInfoService.update(Wrappers.lambdaUpdate(DistributeNodeInfo.class)
            .set(DistributeNodeInfo::getDataStatus, DistributeDataStatusEnum.STATUS_HIS.getStatus())
            .eq(DistributeNodeInfo::getUserId, userId)
            .eq(DistributeNodeInfo::getDistributeType, distributeType)
            .eq(DistributeNodeInfo::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
        distributeNodeRoleService.update(Wrappers.lambdaUpdate(DistributeNodeRole.class)
            .set(DistributeNodeRole::getEndTime, new Date())
            .set(DistributeNodeRole::getDataStatus, DistributeDataStatusEnum.STATUS_HIS.getStatus())
            .eq(DistributeNodeRole::getUserId, userId)
             .eq(DistributeNodeRole::getDistributeType, distributeType)
            .eq(DistributeNodeRole::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
        distributeNodeRoleChainService.update(Wrappers.lambdaUpdate(DistributeNodeRoleChain.class)
            .set(DistributeNodeRoleChain::getDataStatus, DistributeDataStatusEnum.STATUS_HIS.getStatus())
            .eq(DistributeNodeRoleChain::getRefUserId, userId)
            .eq(DistributeNodeRoleChain::getDistributeType, distributeType)
            .eq(DistributeNodeRoleChain::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus()));
    }

    /**
     * 查询所有销售的所有下级
     *
     * @param nodeId (加盟商用户id)
     * @return (用户id集合)
     */
    @Override
    public List<DistributeNodeRoleChain> getAllSaleNodeId(Long nodeId) {
        return getAllSaleUserIdByRole(nodeId, null);
    }

    /**
     * 查询所有销售下级(按角色)
     *
     * @param nodeId (加盟商用户id)
     * @param role   （会员/销售）
     * @return (用户id集合)
     */
    @Override
    public List<DistributeNodeRoleChain> getAllSaleUserIdByRole(Long nodeId, String role) {
        // 查询所有销售下级
        // 获取用户id集合
        return distributeNodeRoleChainService.list(Wrappers.lambdaQuery(DistributeNodeRoleChain.class)
            .eq(DistributeNodeRoleChain::getUpLevelNodeId, nodeId)
                .eq(DistributeNodeRoleChain::getDistributeType, DistributeTypeEnum.TYPE_SALE.getType())
                .eq(DistributeNodeRoleChain::getDataStatus, DistributeDataStatusEnum.STATUS_CURT.getStatus())
            .eq(role != null, DistributeNodeRoleChain::getRefRoleCode, role));
    }


    @Override
    public Map<Long, Set<Long>> getLowNodeUserIds(Integer distributeType,List<Long> userIds, String distributeRoleCode) {
        Map<Long,Set<Long>> map=new HashMap<>();
        if (CollUtil.isNotEmpty(userIds)){
            for (Long userId : userIds) {
                Set<Long> lowLevelUserIds = new HashSet<>();
                List<DistributeNodeRoleChain> distributeNodeRoleChains = distributeNodeRoleChainService.selectDirectLowerNodeUserIds(distributeType,userId);
                lowLevelUserIds.addAll(distributeNodeRoleChains.stream().map(DistributeNodeRoleChain::getRefUserId).collect(Collectors.toSet()));
                if (CollUtil.isNotEmpty(distributeNodeRoleChains)&&distributeRoleCode.equals(DistributeSaleRoleEnum.ROLE_MKMG.getCode())){
                    List<DistributeNodeRoleChain> dpspList=distributeNodeRoleChains.stream().filter(item->item.getRefRoleCode().equals(DistributeSaleRoleEnum.ROLE_DSPD.getCode())).toList();
                    List<Long> dpspUserIds=dpspList.stream().map(DistributeNodeRoleChain::getRefUserId).toList();
                    Map<Long,Set<Long>> idMaps=getLowNodeUserIds(distributeType,dpspUserIds,DistributeSaleRoleEnum.ROLE_DSPD.getCode());
                    idMaps.forEach((k,v)->{lowLevelUserIds.addAll(v);});
                }
                map.put(userId,lowLevelUserIds);
            }
        }
        return map;
    }
}